#pragma once
#include "CTimeline.h"
#include "IATarget.h"
#include "CValue.h"

class CDOCollection;
class CKeyFrameCollection;

class CAnimation :
	public CTimeline
{

	enum AnimationValueOperation
	{
		AnimationValueSet = 0x0,
		AnimationValueClear = 0x1
	};

public: 
	XBOOL IsAnimationValueNull(CDependencyProperty * pdp, CValue * pValue);

protected: 
	CAnimation(CCoreServices * pCore);
	virtual ~CAnimation();
public: 
	static HRESULT Create(CDependencyObject * *, CREATEPARAMETERS *);
	virtual XUINT32 GetTypeIndex() const;
	virtual HRESULT SetValue(CDependencyProperty * pdp, CValue * pValue);
	virtual HRESULT GetValue(CDependencyProperty * pdp, CValue * pValue);
	virtual HRESULT UpdateAnimation(XFLOAT beginTime, const XFLOAT * pParentTime, XBOOL isParentInReverse, XFLOAT combinedSpeedRatio, enum DurationType durationType, XFLOAT durationValue, XBOOL isInReverse, const COptionalFloat & expirationTime, struct IFrameScheduler * pFrameScheduler, XBOOL * pIsIndependentAnimation);
	virtual void GetNaturalDuration(enum DurationType * pDurationType, XFLOAT * prDurationValue);
	virtual HRESULT OnBegin();
	virtual XBOOL IsAnimation();
	HRESULT GetAnimationTargets(CWeakRef * * ppTargetRef, XUINT32 * pnPropertyIndex);
	virtual CDOCollection * GetKeyFrameCollection();
	HRESULT IsIndependentAnimation(CDependencyObject * pTargetObject, XBOOL * pIsIndependentAnimation);
protected: 
	virtual HRESULT NotifyDestruction();
	virtual HRESULT FinalizeIteration(enum FillBehavior parentFillBehavior);
	virtual HRESULT ResolveLocalTarget(CCoreServices * pCoreServices, CTimeline * pParentTimeline);
	virtual HRESULT InterpolateValues(XFLOAT) = 0;
	virtual HRESULT ComputeToUsingFromAndBy() = 0;
	virtual HRESULT ValueAssign(CValue *, CValue *) = 0;
	virtual HRESULT GetAnimationBaseValue() = 0;
	virtual HRESULT CopyTimelineProperties(CRenderTarget * pRenderTarget, CTimeline * pTimeline);
	HRESULT CheckElementUsingAnimatedTarget(CDependencyObject * pTargetObject, xvector<IATarget> * pIATargets, XBOOL * pIsIndependentAnimation);
	XBOOL IsElementInCachedSubtree(CUIElement * pElement, XBOOL startCheckingAtParentElement) const;
	HRESULT ResolveAndClone(CRenderTarget * pRenderTarget, CTimeline * * ppTimeline);
	virtual HRESULT CloneAnimationWithoutProperties(CCoreServices * pCore, CAnimation * * ppCloneAnimation);
private: 
	HRESULT ShouldTickOnUIThread(XBOOL * pTickOnUIThread, XBOOL * pIsIndependentAnimation);
	virtual HRESULT FindIndependentAnimationTargets(CDependencyObject * pTargetObject, CDependencyObject * pSender, xvector<IATarget> * pIATargets, XBOOL * pIsIndependentAnimation);
	HRESULT UpdateAnimationUsingKeyFrames(enum DurationType durationType, XFLOAT durationValue, XBOOL isInReverse, XFLOAT combinedSpeedRatio, struct IFrameScheduler * pFrameScheduler, XBOOL isIndependentAnimation);
	void GetKeyFrameAnimationDuration(CKeyFrameCollection * pKeyFrames, enum DurationType * pDurationType, XFLOAT * prDurationValue);
	HRESULT DoAnimationValueOperation(CValue * pValue, enum CAnimation::AnimationValueOperation operation, XBOOL isValueChangeIndependent);
	XBOOL IsAllowedDependentAnimation();
public: 
	struct  
	{
		XBOOL m_fUsesKeyFrames:1;
		XBOOL m_fFiredDependentAnimationWarning:1;
		XBOOL m_nConcurrentCount:30;
	};

	XBOOL m_enableDependentAnimation;
	CValue m_vFrom;
	CValue m_vTo;
	CValue m_vBy;
	CValue m_vBaseValue;
	CValue m_vNonAnimatedBaseValue;
	CValue m_vCurrentValue;
	CKeyFrameCollection * m_pKeyFrames;
	CDependencyObject * m_pEasingFunction;
protected: 
	CDependencyProperty * m_pDPTo;
	CDependencyProperty * m_pDPFrom;
	CDependencyProperty * m_pDPBy;
	CDependencyProperty * m_pDPValue;
};